General overview

Each of the three intervention files have the same number of observations and the same columns; we row bind all three files to obtain one R object with interventions.

glimpse(interventions)
## Rows: 601,881
## Columns: 47
## $ Mission_ID                         <int64> 10221520001, 10221520002, 1022152…
## $ Service_Name                       <chr> "HA UR MECH AZ St Maarten", "BA KAP…
## $ PostalCode_permanence              <dbl> 2800, 2950, 2060, 2140, 2110, 2340,…
## $ CityName_permanence                <chr> "Mechelen (Mechelen)", "Kapellen (K…
## $ StreetName_permanence              <chr> "Liersesteenweg", "Essenhoutstraat"…
## $ HouseNumber_permanence             <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ Latitude_permanence                <dbl> 51.05102, 51.31208, 51.22249, 51.21…
## $ Longitude_permanence               <dbl> 4.478030, 4.424398, 4.436290, 4.443…
## $ `Permanence_short name`            <chr> "AAMECH01A", "AAKAPE01A", "UAANTW01…
## $ `Permanence_long name`             <chr> "ZW MECHELEN 1", "ZW KAPELLEN 1", "…
## $ Vector_type                        <chr> "Ambulance", "Ambulance", "MUG", "A…
## $ EventType_Firstcall                <chr> "P020 - Intoxication alcohol", "P06…
## $ EventLevel_Firstcall               <chr> "N5", "N5", "N5", "N5", "N5", "N4",…
## $ EventType_Trip                     <chr> "P020 - Intoxication alcohol", "P06…
## $ EventLevel_Trip                    <chr> "N5", "N5", "N1", "N5", "N5", "N4",…
## $ PostalCode_intervention            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ CityName_intervention              <chr> "Lier (Lier)", "Stabroek (Hoevenen)…
## $ Latitude_intervention              <dbl> 51.12496, 51.30626, 51.30626, 51.23…
## $ Longitude_intervention             <dbl> 4.57408, 4.40502, 4.40502, 4.44533,…
## $ Province_intervention              <chr> "ANT", "ANT", "ANT", "ANT", "ANT", …
## $ T0                                 <dttm> 2022-06-01 00:01:34, 2022-06-01 00…
## $ T1                                 <dttm> 2022-06-01 00:03:26, 2022-06-01 00…
## $ T1confirmed                        <dttm> 2022-06-01 00:20:14, 2022-06-01 00…
## $ T2                                 <dttm> 2022-06-01 00:07:34, 2022-06-01 00…
## $ T3                                 <dttm> 2022-06-01 00:17:53, 2022-06-01 00…
## $ T4                                 <dttm> NA, 2022-06-01 00:46:34, 2022-06-0…
## $ T5                                 <dttm> NA, 2022-06-01 00:56:48, 2022-06-0…
## $ T6                                 <dttm> 2022-06-01 00:28:18, 2022-06-01 01…
## $ T7                                 <dttm> 2022-06-01 00:53:17, 2022-06-01 01…
## $ T9                                 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ `Intervention_time (T1Reported)`   <dbl> 14, 10, 13, 15, 10, 10, 9, 11, 5, 7…
## $ `Intervention_time (T1Confirmed)`  <dbl> 0, 10, 13, 12, 9, 10, 8, 11, 5, 6, …
## $ Waiting_time                       <dbl> 16, 13, 32, 19, 15, 12, 14, 16, 7, …
## $ Intervention_duration              <dbl> 27, 65, 63, 32, 73, 50, 59, NA, 73,…
## $ `Departure_time (T1Reported)`      <dbl> 4, 4, 3, 3, 3, 3, 3, 4, 1, 4, 4, 4,…
## $ `Departure_time (T1Confirmed)`     <dbl> 0, 4, 3, 0, 2, 3, 2, 4, 1, 3, 3, 3,…
## $ Unavailable_time                   <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ `Name_destination hospital`        <chr> NA, "HA UR ANTW Jan Palfijn", NA, N…
## $ `PostalCode_destination hospital`  <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ `CityName_destination hospital`    <chr> NA, "Antwerpen (Merksem)", NA, NA, …
## $ `StreetName_destination hospital`  <chr> NA, "Lange Bremstraat", NA, NA, "La…
## $ `HouseNumber_destination hospital` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ `Calculated_travelTime destinatio` <dbl> NA, 678, NA, NA, 530, 859, 838, 284…
## $ `Calculated_Distance destination`  <dbl> NA, 11743, NA, NA, 5468, 13231, 958…
## $ `Number_of transported persons`    <dbl> NA, 1, NA, NA, 1, 1, 1, 1, 2, 3, NA…
## $ Abandon_reason                     <chr> "Verzorgd ter plaatse", NA, NA, "Zo…
## $ time_to_arrive                     <dbl> 16.331467, 12.572600, 32.123283, 18…

There are 10 different possible vectors; Ambulance, Ambulance Disaster, Ambulance Event, Ambulance Exceptional, MUG, MUG Disaster, MUG Event, PIT, PIT Disaster, PIT Event. The vast majority are either regular ambulance, MUG of PIT. An ambulance typically has two ambulance operators which are typically not nurses or doctors. These operators cannot administer medications but typically can use and AED or help the patients with oxygen for breathing. A PIT (Pre-hospital Intervention Team) has one a ambulance operator and a nurse that obtained special training. The nurse may administer medications, take an ECG or blood. In a MUG, there is an emergency doctor and a nurse that received additional training. The nurse typically drives the car (often an SUV).

Permanence

I hypothesize that the permanence indicates the location of the “vector” (PIT/MUG/Ambulance). Latitude and longitude are missing in 2.41 % of the interventions while the postal code is missing in only 0.43% of the interventions. No coordinate system is specified for the longitude and latitude. The range of longitude (2.58895 to 612.739) or latitude (49.53729 to 513.118) does not match with either WGS84, Lambert72, or Lambert2008 coordinate bounds (these are probably the most often used coordinate systems for Belgium). We therefor use the tidygeocoder package to obtain the coordinates of the address.

The figure below shows that this package works well (click on the markers to see the original address) although the coordinates are not found for all addresses (there are some NAs).

However, obtaining the geolocation is quite slow. It takes about 500 seconds to obtain 1000 geolocations in parallel (7 parallel cores). Since there are only 489 unique permanence addresses, it was still feasible to obtain these. It should be noted that 100 (20.45%) geolocations were not found using the tidygeocoder package.

The coordinates of the tidygeocoder package and the specified seem to match quite well, except for a couple of obvious mistakes. The figure below shows the logitude and latitude according to tidygeocoder and according to the raw data. The red lines show the WGS84 bounds for Belgium. Most nonsensical raw longitude/latitude data points seem to be on a straight. We can hypothesize that these numbers should in fact be 10 or 100 times smaller.

Indeed, if we correct the raw data by dividing the lon/lat by either 10 or 100 (depending on the value), all permanence locations lie within the red boundaries and are approximately the same as the tidygeocode locations (see figure below).

Intervention

Similar to the permanence locations, we see that the longitude and latitude contain some nonsensical values. We correct those values accordingly.

## Warning: Removed 834 rows containing missing values (`geom_point()`).
A random sample of 5000 intervention locations with the raw, uncorrected longitude and latitude. The red lines show the bounding box of Belgium for the WGS84 coordinate system.

A random sample of 5000 intervention locations with the raw, uncorrected longitude and latitude. The red lines show the bounding box of Belgium for the WGS84 coordinate system.

## Warning: Removed 823 rows containing missing values (`geom_point()`).
A random sample of 5000 intervention locations with corrected longitude and latitude. The red lines show the bounding box of Belgium for the WGS84 coordinate system.

A random sample of 5000 intervention locations with corrected longitude and latitude. The red lines show the bounding box of Belgium for the WGS84 coordinate system.

Density of interventions in Belgium

## Breaking News: tmap 3.x is retiring. Please test v4, e.g. with
## remotes::install_github('r-tmap/tmap')

Time to arrive to the emergency

The time to arrive to an emergency site will likely depend on how urgent the triage nurse deems the intervention and the time of day (due to availability of ambulances, personnel, and supply and demand). The urgency can be derived from the column EventLevel_Trip which ranges from N0 (most urgent) to N8 (least urgent). 1.84% of interventions have a missing urgency level. By far most interventions have priority level N5.

## `summarise()` has grouped output by 'tod'. You can override using the `.groups`
## argument.
Mean time from the initial call to the arrival at the interventins, depending on time-of-day and the emergency level (on the left). Urgency levels N7 and N8 were left out since we have too few (less than 100) interventions in those categories.

Mean time from the initial call to the arrival at the interventins, depending on time-of-day and the emergency level (on the left). Urgency levels N7 and N8 were left out since we have too few (less than 100) interventions in those categories.

Cardiac arrests

Looking at the interventions data, it can be seen that the column EventType_Trip indicates the reason of the trip i.e. the diagnosis of the patient at arrival of the EMS. Since AEDs are only recommended for cardiac arrests, we filter out the interventions which pertain to cardiac arrests.

cardiac_arrest <- interventions %>%
  filter(str_detect(EventType_Trip, regex("cardiac arrest",
                                          ignore_case = TRUE))) %>%
  mutate(death = 1*(!is.na(Abandon_reason) & Abandon_reason == "Overleden"))

The column Abandon_reason indicates why a transportation to the hospital may not have taken place. For 2817 out of the 8097 cardiac arrests (34.79%), this column contains “overleden” (deceased) meaning the patient died before being transported. Since the overall survival rate for cardiac arrest outside of the hospital in Belgium is only about 5 to 10%, we can assume that many more succomb during or after transportation as well.

Most heart attacks are classified in the highest priority categories N0 of N1

classification of the urgency of a cardiac arrest intervention. One cardiac arrest did not get a priority level assigned.

classification of the urgency of a cardiac arrest intervention. One cardiac arrest did not get a priority level assigned.

Distance to the closest AED

Next to the time to arrival, we also are interested in looking at whether the distance to the closest AED can reduce the probability for the patient to die before being transported.

## Joining with `by = join_by(address)`
## Warning in left_join(., aed_geoloc): Detected an unexpected many-to-many relationship between `x` and `y`.
## ℹ Row 1988 of `x` matches multiple rows in `y`.
## ℹ Row 2543 of `y` matches multiple rows in `x`.
## ℹ If a many-to-many relationship is expected, set `relationship =
##   "many-to-many"` to silence this warning.
Cardiac arrests in red and AED locations in blue.

Cardiac arrests in red and AED locations in blue.

## Warning: Sorting on 'address' results in ties.
## Add extra sorting variables to ensure small diffs.
## 7ea0d5a102c28ec7672b195ad963f0490dfbfd21 
##                      "aed_locations.tsv" 
## c1b733f109f3ed28aec89b160d9c631c717158d1 
##                      "aed_locations.yml"

Some geographical locations for both the AED machines and the cardiac arrests could not be reliably found. Finally, 14928 of the 15257 AED machines and 6868 of the 8097 remain in the final dataset. For each of the cardiac arrests, we determine which AED machine is closest to the intervention site and the distance between both (in meters).

cardiac_arrest_sf_lambert <-  cardiac_arrest_sf %>%
  st_transform(crs = "EPSG:31370")
aed_loc_sf_lambert <- aed_loc_sf %>%
  st_transform(crs = "EPSG:31370")
#transform to lambert to get the distance in meters
idx_closest <- st_nearest_feature(cardiac_arrest_sf_lambert, aed_loc_sf_lambert)
distances <-
  sapply(X = seq_len(length(idx_closest)),
         FUN = function(x){
           a <- st_distance(cardiac_arrest_sf_lambert[x,],
                            aed_loc_sf_lambert[idx_closest[x],])
           return(drop_units(a))
           })
cardiac_arrest_sf$distance_closest_idx <- idx_closest
cardiac_arrest_sf$distance_closest_distance <- distances
cardiac_arrest <- cardiac_arrest %>%
  left_join(cardiac_arrest_sf %>%
              st_drop_geometry())
## Joining with `by = join_by(Mission_ID, Service_Name, PostalCode_permanence,
## CityName_permanence, StreetName_permanence, HouseNumber_permanence,
## Latitude_permanence, Longitude_permanence, `Permanence_short name`,
## `Permanence_long name`, Vector_type, EventType_Firstcall, EventLevel_Firstcall,
## EventType_Trip, EventLevel_Trip, PostalCode_intervention,
## CityName_intervention, Province_intervention, T0, T1, T1confirmed, T2, T3, T4,
## T5, T6, T7, T9, `Intervention_time (T1Reported)`, `Intervention_time
## (T1Confirmed)`, Waiting_time, Intervention_duration, `Departure_time
## (T1Reported)`, `Departure_time (T1Confirmed)`, Unavailable_time,
## `Name_destination hospital`, `PostalCode_destination hospital`,
## `CityName_destination hospital`, `StreetName_destination hospital`,
## `HouseNumber_destination hospital`, `Calculated_travelTime destinatio`,
## `Calculated_Distance destination`, `Number_of transported persons`,
## Abandon_reason, time_to_arrive, full_address_permanence, latitude_permanence,
## longitude_permanence, Longitude_permanence_corrected,
## Latitude_permanence_corrected, death)`
save(cardiac_arrest, file = paste0(datafolder, "/cardiac_arrest.Rdata"))